package vdom

import (
	"io"
	"fmt"
	"strings"
	"reflect"
)


type InspectContext struct {
	GetHandlerId  func(*EventHandler)(string,bool)
}
func Inspect(node *Node, ctx InspectContext) string {
	var buf strings.Builder
	writeNode(&buf, node, ctx, 0, 2)
	return buf.String()
}

func writeNode (
	buf io.Writer, node *Node, ctx InspectContext,
	depth uint, indent uint,
) {
	writeBlank(buf, depth, indent)
	fmt.Fprintf(buf, "<!-- %X -->", reflect.ValueOf(node).Pointer())
	writeLineFeed(buf)
	writeBlank(buf, depth, indent)
	writeRaw(buf, "<")
	writeRaw(buf, node.Tag)
	writeAttrs(buf, node.Attrs)
	writeEvents(buf, node.Events, ctx)
	writeStyles(buf, node.Styles)
	writeRaw(buf, ">")
	writeLineFeed(buf)
	if node.Content != emptyContent {
		switch content := node.Content.(type) {
		case *Text:
			if len(*content) > 0 {
				writeBlank(buf, (depth + 1), indent)
				writeHtmlTextString(buf, string(*content))
				writeLineFeed(buf)
			}
		case *Children:
			for _, child := range *content {
				writeNode(buf, child, ctx, (depth + 1), indent)
			}
		}
	}
	writeBlank(buf, depth, indent)
	writeRaw(buf, "</")
	writeRaw(buf, node.Tag)
	writeRaw(buf, ">")
	writeLineFeed(buf)
}
func writeAttrs(buf io.Writer, attrs *Attrs) {
	if attrs == emptyAttrs { return }
	attrs.Data.ForEach(func(key string, value string) {
		writeRaw(buf, " ")
		writeRaw(buf, key)
		writeRaw(buf, "=")
		writeQuotedString(buf, value)
	})
}
func writeStyles(buf io.Writer, styles *Styles) {
	if styles == emptyStyles { return }
	writeRaw(buf, " style=\"")
	styles.Data.ForEach(func(name string, value string) {
		writeRaw(buf, name)
		writeRaw(buf, ":")
		writeRaw(buf, value)
		writeRaw(buf, ";")
	})
	writeRaw(buf, "\"")
}
func writeEvents(buf io.Writer, events *Events, ctx InspectContext) {
	if events == emptyEvents { return }
	events.Data.ForEach(func(name string, handler *EventHandler) {
		writeRaw(buf, " ")
		writeRaw(buf, "@")
		writeRaw(buf, name)
		writeRaw(buf, "=\"")
		var id, exists = ctx.GetHandlerId(handler)
		if exists {
			fmt.Fprintf(buf, "%s", id)
		} else {
			fmt.Fprintf(buf, "(invalid)")
		}
		writeRaw(buf, "\"")
	})
}


